package productions;

import exceptions.ParserException;
import lexico.ErrorTable;
import lexico.SymbolTable;
import lexico.TokenClass;

/**
 * @author heekinho
 */
public class ConstanteProduction extends AbstractProductionRule {
    /* Muitos dos métodos irão precisar de algo assim: */

    private static ConstanteProduction instance = new ConstanteProduction();

    public static ConstanteProduction getInstance() {
        return instance;
    }

    
    /**
     * Regra: constante : 'constantes' tipo_primitivo IDENTIFIER '=' ('STRING' | 'NUMERIC' | 'CHARACTER' | 'VERDADEIRO' | 'FALSO') ';'
     * @return
     * @throws ParserException
     */
    @Override
    public boolean analyze(SymbolTable st, ErrorTable et) throws ParserException {
        if (!basicParse(st, TokenClass.KEYWORD_CONSTANTES)) {
            return false;
        }
        if (!TipoPrimitivoProduction.getInstance().analyze(st, et)) {
            return skipUntilSynchronize(st, et, "Era esperado um tipo primitivo.");
        }
        if (!basicParse(st, TokenClass.IDENTIFIER)) {
            return skipUntilSynchronize(st, et, "Era esperado um identificador.");
        }
        if (!basicParse(st, TokenClass.OPERATOR_ASSIGNMENT)) {
            return skipUntilSynchronize(st, et, "Era esperado um '='.");
        }

        if (!(basicParse(st, TokenClass.STRING) || basicParse(st, TokenClass.CARACTERE)
                || basicParse(st, TokenClass.NUMERIC) || basicParse(st, TokenClass.NUMERIC_REAL)
                || basicParse(st, TokenClass.KEYWORD_VERDADEIRO) || basicParse(st, TokenClass.KEYWORD_FALSO))) {
            return skipUntilSynchronize(st, et, "Era esperado string ou caractere ou número ou valor lógico.");
        }

        if (!basicParse(st, TokenClass.DELIMITER_SEMICOLON)) {
            return skipUntilSynchronize(st, et, "Era esperado um ';'.");
        }

        return true;
    }

    @Override
    protected void populateFirst() {
        first.add(TokenClass.KEYWORD_CONSTANTES);
    }

    @Override
    protected void populateFollow() {
        //from declarations.follow
        follow.add(TokenClass.KEYWORD_FUNCAO);

        //from tipodefinido.first
        follow.add(TokenClass.KEYWORD_TIPO);

        //from variaveis.first
        follow.add(TokenClass.KEYWORD_VARIAVEIS);

    }
}
